// 判断是否是原生标签
let isReservedTag = (tag) => {
    return ["a", "div", "span", "button", "ul", "li", "h1", "h2", "h3", "h4", "h5", "h6", "p", "input", "img"].includes(tag)
}

// 创建虚拟节点
export function createElementVNode(vm, tag, prop, ...children) {
    if (!prop) {
        prop = {}
    }
    let key = prop.key
    if (key) {
        delete prop.key
    }
    if (isReservedTag(tag)) {
        return vnode(vm, tag, prop, key, children, undefined)
    } else {
        // 创建组件的虚拟节点
        return createTemplateVNode(vm, tag, prop, key, children)
    }
}

function createTemplateVNode(vm, tag, data, key, children) {
    // 从全局中的component中获取对应的组件，应为之前已经合并过了，所以这里可以直接获取
    let Core = vm.$options.components[tag]
    // 这里有两种情况，如果是自己组件本身定义的一个子组件，则拿到的直接是一个对象，里面有一个template
    // 否则会往原型链上找，找到的是通过 Vue.component 定义的组件，拿到的是一个Sub构造函数
    if (typeof Core === "object") {
        // 需要将对象变成Sub构造函数
        Core = vm.$options._base.extend(Core)
    }
    data.hook = {
        init(vnode) {
            // 从返回的vnode上获取componentsOptions中的Core
            let instance = vnode.componentsInstance = new vnode.componentsOptions.Core
            instance.$mount()
        }
    }
    return vnode(vm, tag, data, key, children = [], undefined, {Core})
}


// 创建文本节点
export function createTextVNode(vm, text) {
    return vnode(vm, undefined, undefined, undefined, undefined, text)
}

function vnode(vm, tag, data, key, children = [], text, componentsOptions) {
    children = children.filter(Boolean)
    return {
        vm,
        tag,
        data,
        key,
        children,
        text,
        componentsOptions
    }
}

// 判断两个节点是否一致
export function isSameVNode(oldVNode, newVNode) {
    // 对比两个节点的tag和key是否都一样，如果都一样，就认为这两个节点是一样的
    return oldVNode.tag === newVNode.tag && oldVNode.key === newVNode.key
}